
using namespace std;
#include <ComPort.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <sys/time.h>

// Demo pilotage du PCF8591 avec un module USB I2C
// Python:
// >> import serial
// >> pcf=serial.Serial("/dev/ttyUSBx", 19200, timeout=1)
// >> pcf.write("\x55\x91\x40\x05") # recupere 5 mesures
// >> mes=pcf.read(5)
// >> mes

int main()
{
	char buffer[128];

	ComPort port("/dev/ttyUSB0", 19200, 2);

	port.openPort();

	int myport = port.getPort();

	// Firmware Version
	port.getUSBI2CFirmwareRevision();
	usleep(10000);
	port.readBytes(buffer, 1);
	printf("ISB I2C Firmware Revision = %d\n", buffer[0]);

	// Analog In
	char address     = 0b10010000; // PCF8591 Address -> ! en accord avec config pins A0, A1 & A2
	char controlByte = 0b01000000; // PCF8591 Control Byte (page 6 datasheet)
	int length = 5; // nombre d'octets a recuperer: 1, 2, 3, 4, 5, .. 64 maxi
	                // ! le 1er byte appartient au cycle de lecture precedent
	                // ou = x80 si 1er cycle de lecture apres mise sous tension

	//struct itimerval start, end;
	//long outtime, intime;

while(1)
{
//usleep(10000);

	port.readBytesFromOneByteAddressedI2CDevice(address, controlByte, length);
	//usleep(20000); // laisse du temps executer les I/Os

	// USLEEP peut etre remplace par le code suivant :

	//getitimer(ITIMER_PROF, &start);
	int count = 0, loopout = 0;
	do // boucle en attendant d'avoir le bon nombre de bytes dans l'output buffer
	{
	 ioctl(myport, TIOCOUTQ, &count); // bytes dans l'output buffer
	 loopout++;
//	 printf("[W] #%d wait... still %d bytes in buffer\r",loop, count);
	 	 if ( loopout > 10000 )
	 	 {
	 		 printf("TROP LONG !\n");
	 		 exit(-1);
	 		 break; // on sort si ca dure trop longtemps
	 	 }
	} while ( count > 0 );
	//getitimer(ITIMER_PROF, &end);
	//outtime = end.it_value.tv_usec - start.it_value.tv_usec;
//  printf("\nInfo : %d loops\n",loopout-1);

    // attendre reponse PCF
	//getitimer(ITIMER_PROF, &start);
	count = 0;
	int loopin = 0;
	do // boucle en attendant de recevoir le bon nombre de bytes dans l'input buffer
	{
	 ioctl(myport, TIOCINQ, &count); // bytes dans l'input buffer
	 loopin++;
//	 printf("[R] #%d wait...still %d bytes in buffer\r",loop, count);
	 	 if ( loopin > 100000 )
	 	 {
	 		 printf("TROP LONG !\n");
	 		 exit(-1);
	 		 break; // on sort si ca dure trop longtemps
	 	 }
	} while ( count < length);
	//getitimer(ITIMER_PROF, &end);
	//intime = end.it_value.tv_usec - start.it_value.tv_usec;
//    printf("\nInfo : %d loops\r",loop-1);

    // le buffer a recu la bonne quantite de bytes, on peut les lire
 	port.readBytes(buffer, length);

	float moyenne = 0.0;
	for(int i=0; i < length; i++)
	{
	 //printf("VOLT = %d\n", buffer[i] & 255);
      if ( i >= 1 ) moyenne += (float)(buffer[i] & 255);
	}
	moyenne = (moyenne/(length-1))/255.0*5.0;
	printf("(OUT #%.5d loops) (IN #%.5d loop) Analog In = %.2f [V]\r", loopout, loopin, moyenne);
	//printf("(OUT #%.5d loops in %.6d [usec]) (IN #%.5d loops in %.6d [usec]) Analog In = %.2f [V]\r", loopout, outtime, loopin, intime, moyenne);
}

	// Analog Out
	char analogValue[1];
	analogValue[0] = 128;
	port.writeBytesToOneByteAddressedI2CDevice(address, controlByte, analogValue, 1);
	//usleep(20000);
    printf("\nAnalog Out Set to %u -> %f [V]", analogValue[0] & 255, (float)(analogValue[0]&255)/255.0*5.0);


	port.closePort();

	return 0;
}
